/*
 * Copyright 2009-2010 Nanjing RedOrange ltd (http://www.red-orange.cn)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package redora.client.ui;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasAllMouseHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.dom.client.MouseWheelEvent;
import com.google.gwt.event.dom.client.MouseWheelHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.BidiUtils;
import com.google.gwt.i18n.client.HasDirection;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWordWrap;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * A widget that creates a &lt;label&gt; tag. This code was based on the Google
 * com.google.gwt.user.client.ui.Label widget that creates a DIV/SPAN, with all
 * of the deprecated code removed.
 * 
 * @author Nanjing RedOrange (http://www.red-orange.cn)
 */
public class Label extends Widget implements HasHorizontalAlignment, HasText,
        HasWordWrap, HasDirection, HasClickHandlers, HasAllMouseHandlers {

    /**
     * Creates a Label widget that wraps an existing &lt;div&gt; or &lt;span&gt;
     * element.
     * 
     * This element must already be attached to the document. If the element is
     * removed from the document, you must call
     * {@link RootPanel#detachNow(Widget)}.
     * 
     * @param element
     *            the element to be wrapped
     * @return Label
     */
    public static Label wrap(Element element) {
        // Assert that the element is attached.
        assert Document.get().getBody().isOrHasChild(element);

        Label label = new Label(element);

        // Mark it attached and remember it for cleanup.
        label.onAttach();
        RootPanel.detachOnWindowClose(label);

        return label;
    }

    private HorizontalAlignmentConstant horzAlign;

    /**
     * Creates an empty label.
     */
    public Label() {
        setElement(Document.get().createLabelElement());
        setStyleName("redoraFormLabel");
    }

    /**
     * Creates a label with the specified text.
     * 
     * @param text
     *            the new label's text
     */
    public Label(String text) {
        this();
        setText(text);
    }

    /**
     * Creates a label with the specified text.
     * 
     * @param text
     *            the new label's text
     * @param wordWrap
     *            <code>false</code> to disable word wrapping
     */
    public Label(String text, boolean wordWrap) {
        this(text);
        setWordWrap(wordWrap);
    }

    /**
     * Creates a label with the specified text and connected to a input widget.
     * 
     * @param text
     *            the new label's text
     * @param elementID
     *            <code>false</code> to disable word wrapping
     */
    public Label(String text, String elementID) {
        this(text);
        setConnectedInputId(elementID);
    }

    /**
     * This constructor may be used by subclasses to explicitly use an existing
     * element. This element must be a &lt;label&gt; element.
     * 
     * @param element
     *            the element to be used
     */
    protected Label(Element element) {
        setElement(element);
        assert element.getTagName().equalsIgnoreCase("label");
    }

    public void setConnectedInputId(String inputId) {
        this.getElement().setAttribute("for", inputId);
    }

    public HandlerRegistration addClickHandler(ClickHandler handler) {
        return addDomHandler(handler, ClickEvent.getType());
    }

    public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
        return addDomHandler(handler, MouseDownEvent.getType());
    }

    public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
        return addDomHandler(handler, MouseMoveEvent.getType());
    }

    public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
        return addDomHandler(handler, MouseOutEvent.getType());
    }

    public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
        return addDomHandler(handler, MouseOverEvent.getType());
    }

    public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
        return addDomHandler(handler, MouseUpEvent.getType());
    }

    public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
        return addDomHandler(handler, MouseWheelEvent.getType());
    }

    public Direction getDirection() {
        return BidiUtils.getDirectionOnElement(getElement());
    }

    public HorizontalAlignmentConstant getHorizontalAlignment() {
        return horzAlign;
    }

    public String getText() {
        return getElement().getInnerText();
    }

    /**
     * Returns the HTML if it is set to HTML.
     * 
     * @return the getInnerHTML of the element.
     */
    public String getHTML() {
        return getElement().getInnerHTML();
    }

    public boolean getWordWrap() {
        return !getElement().getStyle().getProperty("whiteSpace").equals(
                "nowrap");
    }

    public void setDirection(Direction direction) {
        BidiUtils.setDirectionOnElement(getElement(), direction);
    }

    public void setHorizontalAlignment(HorizontalAlignmentConstant align) {
        horzAlign = align;
        getElement().getStyle().setProperty("textAlign",
                align.getTextAlignString());
    }

    public void setText(String text) {
        getElement().setInnerText(text);
    }

    /**
     * Sets the label value to be the specified HTML.
     * 
     * @param html
     *            the HTML value of the label.
     */
    public void setHTML(String html) {
        getElement().setInnerHTML(html);
    }

    public void setWordWrap(boolean wrap) {
        getElement().getStyle().setProperty("whiteSpace",
                wrap ? "normal" : "nowrap");
    }
}
